package testutils

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"higame/modules/log"
	"higame/routes"
	"io/ioutil"
	"net/http/httptest"
	"net/url"
	"strings"
	"sync"
)

var once sync.Once
var test *Test

type Test struct {
	engine *gin.Engine
	token  string
}

func GetInstance() *Test {
	once.Do(func() {
		test = &Test{}
		test.engine = routes.Setup()
	})
	return test
}

// Get 根据特定请求uri，发起get请求返回响应
func (t *Test) Get(uri string) []byte {
	// 构造get请求
	req := httptest.NewRequest("GET", uri, nil)
	// 初始化响应
	w := httptest.NewRecorder()

	// 调用相应的handler接口
	t.engine.ServeHTTP(w, req)

	// 提取响应
	result := w.Result()
	defer result.Body.Close()

	// 读取响应body
	body, _ := ioutil.ReadAll(result.Body)
	return body
}

// PostJson 根据特定请求uri和参数param，以Json形式传递参数，发起post请求返回响应
func (t *Test) Post(uri string, param url.Values) []byte {
	// 构造post请求，json数据以请求body的形式传递
	req := httptest.NewRequest("POST", uri, strings.NewReader(param.Encode()))
	if t.token != "" {
		req.Header.Set("Authorization", "Bearer "+t.token)
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
	// 初始化响应
	w := httptest.NewRecorder()

	// 调用相应的handler接口
	t.engine.ServeHTTP(w, req)

	// 提取响应
	result := w.Result()
	defer result.Body.Close()
	// 读取响应body
	body, _ := ioutil.ReadAll(result.Body)
	return body
}

func (t *Test) PostForm(uri string, param string) []byte {
	// 构造post请求，json数据以请求body的形式传递
	req := httptest.NewRequest("POST", uri, strings.NewReader(param))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
	if t.token != "" {
		req.Header.Set("Authorization", "Bearer "+t.token)
	}
	// 初始化响应
	w := httptest.NewRecorder()

	// 调用相应的handler接口
	t.engine.ServeHTTP(w, req)

	// 提取响应
	result := w.Result()
	defer result.Body.Close()
	// 读取响应body
	body, _ := ioutil.ReadAll(result.Body)
	return body
}

func (t *Test) ParseJson(data []byte) (m map[string]interface{}, err error) {
	var j map[string]interface{}
	err = json.Unmarshal(data, &j)
	return j, err
}

func (t *Test) Login(username string, password string) {
	postData := fmt.Sprintf("username=%s&password=%s", username, password)
	res := t.PostForm("/user/login", postData)
	log.Info.Println(t.ParseJson(res))
	if m, err := t.ParseJson(res); err == nil {
		pass := m["code"].(float64) == 200
		if pass {
			t.token = m["token"].(string)
		} else {
			log.Error.Println("登录失败")
		}
	} else {
		log.Error.Println(err)
	}
}
